package com.SNQ.project.English_speaking_learning_system.service.impl;

import com.SNQ.project.English_speaking_learning_system.common.result.PageResult;
import com.SNQ.project.English_speaking_learning_system.common.result.Result;
import com.SNQ.project.English_speaking_learning_system.common.utils.AliOssUtil;
import com.SNQ.project.English_speaking_learning_system.mapper.ArticleMapper;
import com.SNQ.project.English_speaking_learning_system.mapper.CategoryMapper;
import com.SNQ.project.English_speaking_learning_system.pojo.dto.ArticleDTO;
import com.SNQ.project.English_speaking_learning_system.pojo.dto.ArticlePageQueryDTO;
import com.SNQ.project.English_speaking_learning_system.pojo.entity.Article;
import com.SNQ.project.English_speaking_learning_system.pojo.vo.ArticleVO;
import com.SNQ.project.English_speaking_learning_system.service.ArticleService;
import com.SNQ.project.English_speaking_learning_system.config.SpeechSynthesizerDemo;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private AliOssUtil aliOssUtil;

    /**
     * 创建文章信息
     * @param articleDTO
     */
    public void createArticle(ArticleDTO articleDTO) throws Exception {
        Article article = new Article();

        BeanUtils.copyProperties(articleDTO,article);

        String fname = SpeechSynthesizerDemo.main(article.getContent(),article.getTitle());

        // 自定义文件路径和名称，D:/code/Spring/English-speaking-learning-system/audio/ 下的 filename.mp3
        String fileName = fname; // 你可以用具体的文章标题或其他方式生成文件名
        String localFilePath = fileName;

        // 打开本地文件作为输入流
        File file = new File(localFilePath);
        FileInputStream fis = new FileInputStream(file);

        // 设置文件后缀名
        String extension = ".mp3";

        // 生成 OSS 上的文件名（使用 UUID 避免重名）
        String objectName = UUID.randomUUID().toString() + extension;

        // 使用Java 8兼容的方式读取文件字节流
        byte[] fileBytes = new byte[(int) file.length()];
        try {
            fis.read(fileBytes);
        } finally {
            fis.close();
        }

        // 调用 aliOssUtil 上传方法，传入文件的字节流
        String filePath = aliOssUtil.upload(fileBytes, objectName);

        article.setAudioUrl(filePath);

        //向文章表插入一条数据
        articleMapper.insert(article);
    }

    /**
     * 文章分页查询
     * @param articlePageQueryDTO
     * @return
     */
    public PageResult pageQuery(ArticlePageQueryDTO articlePageQueryDTO){
        PageHelper.startPage(articlePageQueryDTO.getPage(), articlePageQueryDTO.getPageSize());
        Page<ArticleVO> page = articleMapper.pageQuery(articlePageQueryDTO);
        return new PageResult(page.getTotal(), page.getResult());
    }

    /**
     * 文章批量删除
     * @param ids
     */
    @Transactional
    public void deleteBatch(List<Long> ids) {
        //删除文章表中的文章数据
        for (Long id : ids) {
            articleMapper.deleteById(id);
        }
    }

    /**
     * 根据id查询文章信息
     * @param id
     * @return
     */
    public ArticleVO getById(Long id) {
        //根据id查询文章数据
        Article article = articleMapper.getById(id);

        //将查询到的数据封装到VO
        ArticleVO articleVO = new ArticleVO();
        BeanUtils.copyProperties(article, articleVO);

        // 获取分类名称并设置到VO
        String categoryName = categoryMapper.getCategoryNameById(article.getCategoryId());
        articleVO.setCategoryName(categoryName);

        return articleVO;
    }

    /**
     * 根据id修改文章基本信息
     * @param articleDTO
     */
    public void update(ArticleDTO articleDTO) {
        Article article = new Article();
        BeanUtils.copyProperties(articleDTO, article);

        //修改文章表基本信息
        articleMapper.update(article);
    }

    /**
     * 根据分类id查询文章
     * @param categoryId
     * @return
     */
    public List<Article> list(Long categoryId) {
        Article article = Article.builder()
                .categoryId(categoryId)
                .build();
        return articleMapper.list(article);
    }

    public int compareTextSimilarity(String recognizedText, String articleContent) {
        // 简单的相似度计算，可以根据业务需求选择更复杂的算法
        int score = 0;

        if (recognizedText == null || articleContent == null) {
            return score;
        }

        // 示例：如果两个文本完全相同，打100分
        if (recognizedText.equals(articleContent)) {
            score = 100;
        } else {
            // 简单示例：计算相似度，比如比较长度，或使用 Levenshtein 距离等
            int maxLength = Math.max(recognizedText.length(), articleContent.length());
            int editDistance = calculateLevenshteinDistance(recognizedText, articleContent);

            // 计算得分，基于编辑距离，越小得分越高
            score = (int) ((1 - ((double) editDistance / maxLength)) * 100);
        }

        return score;
    }


    public int calculateLevenshteinDistance(String s1, String s2) {
        int[][] dp = new int[s1.length() + 1][s2.length() + 1];

        for (int i = 0; i <= s1.length(); i++) {
            for (int j = 0; j <= s2.length(); j++) {
                if (i == 0) {
                    dp[i][j] = j;
                } else if (j == 0) {
                    dp[i][j] = i;
                } else {
                    int cost = (s1.charAt(i - 1) == s2.charAt(j - 1)) ? 0 : 1;
                    dp[i][j] = Math.min(dp[i - 1][j] + 1,  // 删除
                            Math.min(dp[i][j - 1] + 1,   // 插入
                                    dp[i - 1][j - 1] + cost));  // 替换
                }
            }
        }

        return dp[s1.length()][s2.length()];
    }


}
